package com.taobaolite.user;

import com.taobaolite.user.admin.AdminRepository;
import com.taobaolite.user.guest.Guest;
import com.taobaolite.user.guest.GuestRepository;
import com.taobaolite.user.store.Store;
import com.taobaolite.user.store.StoreRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import static com.taobaolite.user.UserType.*;

@Service
public class UserService {

    private final UserRepository userRepo;
    private final AdminRepository adminRepo;
    private final StoreRepository storeRepo;
    private final GuestRepository guestRepo;

    @Autowired
    public UserService(UserRepository userRepo, AdminRepository adminRepo, StoreRepository storeRepo, GuestRepository guestRepo) {
        this.userRepo = userRepo;
        this.adminRepo = adminRepo;
        this.storeRepo = storeRepo;
        this.guestRepo = guestRepo;
    }

    public List<UserBody> getUser(Long userId) {
        User user = userRepo.findById(userId)
                .orElseThrow(() -> new ResponseStatusException(
                        HttpStatus.NOT_FOUND,
                        "User with ID " +
                                userId +
                                " does not exist. " +
                                "Please check database."
                ));

        List<UserBody> userResponse = new ArrayList<>();

        if (user.getType() == ADMIN) {
            List<Long> ids = userRepo.getAllUserId();
            for (Long id : ids) {
                userResponse.add(generateUserBody(id));
            }
        } else {
            userResponse.add(generateUserBody(userId));
        }

        return userResponse;
    }

//    //通过用户名搜索user
//    public UserBody getUser(String username){
//        User user = userRepo.findByUsername(username).orElseThrow(() -> new ResponseStatusException(
//                HttpStatus.NOT_FOUND,
//                "User with name " +
//                        username +
//                        " does not exist. " +
//                        "Please check database."
//        ));
//        return generateUserBody(user.getUserId());
//    }

    //检查登录表单
    public UserBody loginCheck(String username, String password){
//        UserBody userResponse = getUser(username);

        User user = userRepo.findByUsername(username).orElseThrow(() -> new ResponseStatusException(
                HttpStatus.NOT_FOUND,
                "User with name " +
                        username +
                        " does not exist. " +
                        "Please check database."
        ));

        if(password.equals(user.getPassword())){
            return generateUserBody(user.getUserId());
        }else{
            throw new ResponseStatusException(
                    HttpStatus.UNAUTHORIZED,
                    "Username " +
                            username +
                            " or password " +
                            password +
                            " was wrong."
            );
        }

    }

    public UserBody generateUserBody(Long userId) {
        User user = userRepo.findById(userId)
                .orElseThrow(() -> new ResponseStatusException(
                        HttpStatus.NOT_FOUND,
                        "User with ID " +
                                userId +
                                " does not exist. " +
                                "Please check database."
                ));

        UserBody userBody = new UserBody();
        userBody.setUsername(user.getUsername());
        userBody.setUserId(userId);
        userBody.setBalance(user.getBalance());
        userBody.setEmail(user.getEmail());
        userBody.setType(user.getType());
//        userBody.setPassword(user.getPassword());

        switch (user.getType()) {
            case ADMIN:
                break;
            case STORE:
                Store store = storeRepo.findById(userId)
                        .orElseThrow(() -> new ResponseStatusException(
                                HttpStatus.NOT_FOUND,
                                "Store with ID " +
                                        userId +
                                        " does not exist. " +
                                        "Please check database."
                        ));

                userBody.setDescription(store.getDescription());
                userBody.setName(store.getName());
                userBody.setLogoPath(store.getLogoPath());

                break;
            case GUEST:
                Guest guest = guestRepo.findById(userId)
                        .orElseThrow(() -> new ResponseStatusException(
                                HttpStatus.NOT_FOUND,
                                "Guest with ID " +
                                        userId +
                                        " does not exist. " +
                                        "Please check database."
                        ));

                userBody.setName(guest.getName());
        }
        return userBody;
    }

//    public List<User> getUsers() {
//        List<User> userList = userRepo.findAll();
//        if (userList.size() == 0) {
//            throw new ResponseStatusException(
//                    HttpStatus.NOT_FOUND,
//                    "User list is empty!"
//            );
//        }
//        return userRepo.findAll();
//    }

    @Transactional
    public void updateUser(Long userId, UserBody new_user) {

        User user = userRepo.findById(userId)
                .orElseThrow(() -> new ResponseStatusException(
                        HttpStatus.NOT_FOUND,
                        "User with ID " +
                                userId +
                                " does not exist."
                ));

        // Update password
        if (new_user.getPassword() != null && new_user.getPassword().length() > 0) {
            user.setPassword(new_user.getPassword());
        }

        // Update email
        if (new_user.getEmail() != null && new_user.getEmail().length() > 0 &&
        !Objects.equals(new_user.getEmail(), user.getEmail())) {
            Optional<User> userOptional = userRepo.findByEmail(new_user.getEmail());
            if (userOptional.isPresent()) {
                throw new ResponseStatusException(
                        HttpStatus.CONFLICT,
                        "User with email " +
                                new_user.getEmail() +
                                " already exists."
                );
            }
            user.setEmail(new_user.getEmail());
        }

        // Update balance
        updateBalance(userId, new_user.getBalance());

        // Update for Store
        if (new_user.getType() == STORE) {
            Store store = storeRepo.findById(userId)
                    .orElseThrow(() -> new ResponseStatusException(
                            HttpStatus.NOT_FOUND,
                            "Store with ID " +
                                    userId +
                                    " does not exist."
                    ));

            // Update store name
            store.setName(new_user.getName());

            // Update store logoPath
            store.setLogoPath(new_user.getLogoPath());

            // Update store description
            store.setDescription(new_user.getDescription());
        } else if (new_user.getType() == GUEST) { // Update for Guest
            Guest guest = guestRepo.findById(userId)
                    .orElseThrow(() -> new ResponseStatusException(
                            HttpStatus.NOT_FOUND,
                            "Guest with ID " +
                                    userId +
                                    " does not exist."
                    ));

            // Update guest name
            guest.setName(new_user.getName());
        }
    }

    @Transactional
    public void updateBalance(Long userId, Double new_balance) {
        User user = userRepo.findById(userId)
                .orElseThrow(() -> new ResponseStatusException(
                        HttpStatus.NOT_FOUND,
                        "User with ID " +
                                userId +
                                " does not exist."
                ));
       user.setBalance(new_balance);
    }

    public User addNewUser(String username, String password, Double balance, UserType type, String email) {
        Optional<User> userOptional = userRepo.findByEmail(email);
        if (userOptional.isPresent()) {
            throw new ResponseStatusException(
                    HttpStatus.CONFLICT,
                    "User with email " +
                            email +
                            " already exists."
            );
        }

        return new User(username, password, balance, type, email);
    }

    public void addAdmin(UserBody userBody) {
        throw new ResponseStatusException(
                HttpStatus.NOT_ACCEPTABLE,
                "You can't add a new admin user!"
        );

//        User newUser = addNewUser(
//                userRequest.getPassword(),
//                userRequest.getBalance(),
//                userRequest.getType(),
//                userRequest.getEmail());
//        Admin newAdmin = new Admin(newUser);
//        adminRepo.save(newAdmin);
    }

    public void addGuest(UserBody userBody) {
        User newUser = addNewUser(
                userBody.getUsername(),
                userBody.getPassword(),
                userBody.getBalance(),
                userBody.getType(),
                userBody.getEmail());
        Guest newGuest = new Guest(newUser, userBody.getName());
        guestRepo.save(newGuest);
    }

    public void addStore(UserBody userBody) {
        User newUser = addNewUser(
                userBody.getUsername(),
                userBody.getPassword(),
                userBody.getBalance(),
                userBody.getType(),
                userBody.getEmail());
        Store newStore = new Store(
                newUser,
                userBody.getName(),
                userBody.getDescription(),
                userBody.getLogoPath());
        storeRepo.save(newStore);
    }
}
